﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using SfdClient.Messaging;
using SfdClient.Resources;

namespace SfdClient.ViewModel
{
    public class FolderBrowserViewModel : WorkingViewModelBase
    {
        public FolderBrowserViewModel()
        {
            if (!IsInDesignMode)
                Messenger.Default.Register<CurrentProjectChangedMessage>
                    (this,
                     message =>
                         {
                             RootFolder = Path.GetFullPath(message.Project.LocalFolder);
                             CurrentItem = new FolderBrowserItem(RootFolder, RootFolder);
                         });
        }

        #region RootFolder Property

        /// <summary>
        /// The <see cref="RootFolder" /> property's name.
        /// </summary>
        public const string RootFolderPropertyName = "RootFolder";

        private string _rootFolder;

        public string RootFolder
        {
            get { return _rootFolder; }

            private set
            {
                if (_rootFolder == value) return;

                _rootFolder = value;
                RaisePropertyChanged(RootFolderPropertyName);
            }
        }

        #endregion

        #region CurrentItem Property

        /// <summary>
        /// The <see cref="CurrentItem" /> property's name.
        /// </summary>
        public const string CurrentItemPropertyName = "CurrentItem";

        private FolderBrowserItem _currentItem;

        public FolderBrowserItem CurrentItem
        {
            get { return _currentItem; }

            private set
            {
                if (_currentItem == value) return;

                _currentItem = value;
                RaisePropertyChanged(CurrentItemPropertyName);
                ExecuteRefreshCommand();
            }
        }

        #endregion  

        #region FolderBrowserItems Property

        /// <summary>
        /// The <see cref="FolderBrowserItems" /> property's name.
        /// </summary>
        public const string FolderBrowserItemsPropertyName = "FolderBrowserItems";

        private ObservableCollection<FolderBrowserItem> _folderBrowserItems;

        public ObservableCollection<FolderBrowserItem> FolderBrowserItems
        {
            get { return _folderBrowserItems; }

            private set
            {
                if (_folderBrowserItems == value) return;

                _folderBrowserItems = value;
                RaisePropertyChanged(FolderBrowserItemsPropertyName);
            }
        }

        #endregion

        #region RefreshCommand

        private ICommand _refreshCommand;

        public ICommand RefreshCommand
        {
            get
            {
                if (_refreshCommand == null)
                    _refreshCommand = new RelayCommand(ExecuteRefreshCommand, CanExecuteRefreshCommand);
                return _refreshCommand;
            }
        }

        public void ExecuteRefreshCommand()
        {
            if (!CanExecuteRefreshCommand())
                return;

            MarkWorking(ResourceLocalizer.Current["FolderBrowserViewModel_AnalyseEnCours"]);

            Task.Factory.StartNew<IEnumerable<FolderBrowserItem>>(
                ()
                =>
                    {
                        var items =
                            Directory.GetDirectories(CurrentItem.FullName).Select(
                                folderName => new FolderBrowserItem(RootFolder, folderName)).ToList();
                        items.AddRange(
                            Directory.GetFiles(CurrentItem.FullName).Select(
                                file => new FolderBrowserItem(RootFolder, file)));

                        return items;

                    }).ContinueWith(
                        task =>
                            {
                                if (!task.IsFaulted)
                                {
                                    FolderBrowserItems = new ObservableCollection<FolderBrowserItem>(task.Result);
                                    MarkNotWorking(ResourceLocalizer.Current["FolderBrowserViewModel_AnalyseTerminee"]);
                                }
                                else
                                {
                                    FolderBrowserItems = null;
                                    MarkNotWorking(string.Format(ResourceLocalizer.Current["FolderBrowserViewModel_AnalyseTermineeAvecErreur"], task.Exception.InnerException.Message));

                                }
                            },
                        TaskScheduler.FromCurrentSynchronizationContext());


        }

        public bool CanExecuteRefreshCommand()
        {
            return CurrentItem != null && !IsInDesignMode;
        }

        #endregion

        #region MoveUpFolderCommand

        private ICommand _moveUpFolderCommand;

        public ICommand MoveUpFolderCommand
        {
            get {
                return _moveUpFolderCommand ??
                       (_moveUpFolderCommand =
                        new RelayCommand(ExecuteMoveUpFolderCommand, CanExecuteMoveUpFolderCommand));
            }
        }

        public void ExecuteMoveUpFolderCommand()
        {
            if (!CanExecuteMoveUpFolderCommand())
                return;
            
            var parent = new FolderBrowserItem(RootFolder, Path.GetDirectoryName(CurrentItem.FullName));
            CurrentItem = parent;
        }

        public bool CanExecuteMoveUpFolderCommand()
        {
            return RootFolder != null && CurrentItem != null && RootFolder != CurrentItem.FullName;
        }

        #endregion

        #region CurrentFolderChangedCommand

        private ICommand _currentFolderChangedCommand;

        public ICommand CurrentFolderChangedCommand
        {
            get {
                return _currentFolderChangedCommand ??
                       (_currentFolderChangedCommand =
                        new RelayCommand<FolderBrowserItem>(ExecuteCurrentFolderChangedCommand,
                                                            CanExecuteCurrentFolderChangedCommand));
            }
        }

        public void ExecuteCurrentFolderChangedCommand(FolderBrowserItem argument)
        {
            if (!CanExecuteCurrentFolderChangedCommand(argument))
                return;

            CurrentItem = argument;
        }

        public bool CanExecuteCurrentFolderChangedCommand(FolderBrowserItem argument)
        {
            return argument != null && argument.IsDirectory;
        }

        #endregion

        #region ShowExplorerCommand

        private ICommand _showExplorerCommand;

        public ICommand ShowExplorerCommand
        {
            get
            {
                if (_showExplorerCommand == null)
                    _showExplorerCommand = new RelayCommand(ExecuteShowExplorerCommand, CanExecuteShowExplorerCommand);
                return _showExplorerCommand;
            }
        }

        public void ExecuteShowExplorerCommand()
        {
            if (!CanExecuteShowExplorerCommand())
                return;

            Process.Start(CurrentItem.FullName);
        }

        public bool CanExecuteShowExplorerCommand()
        {
            return CurrentItem != null;
        }

        #endregion  

    }
}
